/***************************************************************************//**
 * @file     csa37f7x_rcc.h
 * @version  V1.0.0
 * @author   cs2040
 * @date     2020-09-26 PM
 * @brief    该文件包含了RCC各功能参数的定义和函数接口声明
 * 
 * @copyright Copyright (C) 2020 Chipsea Technologies Corp. All rights reserved.
 ****************************************************************************
 * @attention
 *  硬件平台: CSA37F70 评估板V1.0 \n
 *  SDK版本： CSA37F7X_SDK_1.0.0
 * 
 * @par 修改日志:
 * <table>
 * <tr><th>Date        <th>Version  <th>Author    <th>Description
 * <tr><td>2020-09-26  <td>1.0.0    <td>Chipsea MCU Group  <td>创建初始版本
 * </table>
 *
 *****************************************************************************/

#ifndef __CSA37F7x_RCC_H__
#define __CSA37F7x_RCC_H__

// Include external header file.
#include "csa37f7x_sdk.h"

#ifdef __cplusplus
extern "C" {
#endif

/** @addtogroup RCC 时钟复位管理单元(RCC)
  复位有两种：硬件复位和软件复位。时钟控制器为整个芯片提供时钟，包括系统时钟和所有外设时钟。时钟控制器还利用独立的时钟
ON/OFF 控制、时钟源选择和时钟分频器，实现时钟控制功能。<br>
###时钟结构: 
* \image html clock_management.png 
  @{
*/


/**
* @brief  定义外设时钟复位
*/
#define RCC_AHB_PERI_PORTB         BIT(5)                   /*!<GPIOB 时钟复位管理单元 */
#define RCC_AHB_PERI_TICK		   BIT(4)                   /*!<滴答定时器时钟复位管理单元 */ 
#ifdef __CSA37F70__
#define RCC_AHB_PERI_CRC		   BIT(3)                   /*!<CRC校验时钟复位管理单元 */ 
#define RCC_AHB_PERI_HDIV		   BIT(2)                   /*!<硬件除法器时钟复位管理单元 */
#endif
#define RCC_AHB_PERI_ISP		   BIT(1)                   /*!<ISP时钟复位管理单元 */ 
#define RCC_AHB_PERI_PORTA  	   BIT(0)                   /*!<GPIOA 时钟复位管理单元 */ 

/**
* @brief  宏定义检查RCC AHB外设选择
*/
#ifdef __CSA37F70__
#define RCC_AHB_PERI_CHECK(RCC_AHBPeriph)			        (((RCC_AHBPeriph) == RCC_AHB_PERI_PORTB)||\
														    ((RCC_AHBPeriph) == RCC_AHB_PERI_TICK)||\
													        ((RCC_AHBPeriph) == RCC_AHB_PERI_CRC)||\
													        ((RCC_AHBPeriph) == RCC_AHB_PERI_HDIV)||\
													        ((RCC_AHBPeriph) == RCC_AHB_PERI_ISP)||\
													        ((RCC_AHBPeriph) == RCC_AHB_PERI_PORTA))
													        	
#else
#define RCC_AHB_PERI_CHECK(RCC_AHBPeriph)			        (((RCC_AHBPeriph) == RCC_AHB_PERI_PORTB)||\
														    ((RCC_AHBPeriph) == RCC_AHB_PERI_TICK)||\
													        ((RCC_AHBPeriph) == RCC_AHB_PERI_ISP)||\
													        ((RCC_AHBPeriph) == RCC_AHB_PERI_PORTA))
#endif

#ifdef	__CSA37F70__
#define RCC_APB_PERI_TK 		   BIT(29)                  /*!<触摸按键时钟复位管理单元 */
#endif
#define RCC_APB_PERI_AFE		   BIT(28)                  /*!<模拟前端AFE时钟复位管理单元 */ 
#define RCC_APB_PERI_TMR1		   BIT(17)                  /*!<定时器1时钟复位管理单元 */ 
#define RCC_APB_PERI_TMR0		   BIT(16)                  /*!<定时器0时钟复位管理单元 */ 
#define RCC_APB_PERI_I2C		   BIT(8)                   /*!<i2c时钟复位管理单元 */ 
#ifdef	__CSA37F70__
#define RCC_APB_PERI_UART		   BIT(2)                   /*!<串口1时钟复位管理单元 */ 
#else
#define RCC_APB_PERI_USART		   BIT(3)                   /*!<串口2时钟复位管理单元 */ 
#endif
#define RCC_APB_PERI_WWDG		   BIT(0)                   /*!<看门狗时钟复位管理单元 */ 

/**
* @brief  宏定义检查RCC AHB外设选择
*/
#ifdef	__CSA37F70__
#define RCC_APB_PERI_CHECK(RCC_APBPeriph)			        (((RCC_APBPeriph) == RCC_APB_PERI_TK)||\
														    ((RCC_APBPeriph) == RCC_APB_PERI_AFE)||\
													        ((RCC_APBPeriph) == RCC_APB_PERI_TMR1)||\
													        ((RCC_APBPeriph) == RCC_APB_PERI_TMR0)||\
													        ((RCC_APBPeriph) == RCC_APB_PERI_I2C)||\
													        ((RCC_APBPeriph) == RCC_APB_PERI_UART)||\
													        ((RCC_APBPeriph) == RCC_APB_PERI_WWDG))
#else
#define RCC_APB_PERI_CHECK(RCC_APBPeriph)			        (((RCC_APBPeriph) == RCC_APB_PERI_AFE)||\
													        ((RCC_APBPeriph) == RCC_APB_PERI_TMR1)||\
													        ((RCC_APBPeriph) == RCC_APB_PERI_TMR0)||\
													        ((RCC_APBPeriph) == RCC_APB_PERI_I2C)||\
													        ((RCC_APBPeriph) == RCC_APB_PERI_USART)||\
													        ((RCC_APBPeriph) == RCC_APB_PERI_WWDG))
#endif


/**
 * @brief  PLL倍频选择，
 */
typedef enum
{
	RCC_PLL_CLK_24M = 0x00,                                 /*!<PLL 24M时钟 */
	RCC_PLL_CLK_48M = 0x01,                                 /*!<PLL 48M时钟 */
}rcc_pllclk_t;

/**
 * @brief  芯片复位选择，
 */
typedef enum
{
	RCC_CHIP_RESET = 0x00,                                  /*!<芯片复位 */
	RCC_MCU_RESET  = 0x01,                                  /*!<MCU软复位 */
}rcc_chiprst_t;

/**
 * @brief  Flash读写速度选择\n  注意：当配置HCLK频率大于24MHz时，需要先设置LATENCY =1
 */
typedef enum
{
	FLASH_READ_0_CYCLE = 0x00,                             /*!<0个等待周期，适用于0Hz<HCLK≤24MHz */
	FLASH_READ_1_CYCLE = 0x01,                             /*!<1个等待周期，适用于24Hz<HCLK≤48MHz */
}rcc_flashread_t;

/**
 * @brief  时钟源输出选择
 */
#ifdef  __CSA37F70__
typedef enum
{
	RCC_MCU_CLKOUT_NOCLK  = 0x00,                           /*!<无时钟输出 */
	RCC_MCU_CLKOUT_HIRC14 = 0x01,                           /*!<HIRC14时钟输出 */
	RCC_MCU_CLKOUT_LIRC2  = 0x02,                           /*!<LIRC2时钟输出 */
	RCC_MCU_CLKOUT_PLL    = 0x03,                           /*!<PLL时钟输出 */
	RCC_MCU_CLKOUT_SYSCLK = 0x04,                           /*!<系统时钟输出 */
	RCC_MCU_CLKOUT_TK     = 0x05,                           /*!<TK时钟输出 */
	RCC_MCU_CLKOUT_CVC    = 0x06,                           /*!<CVC时钟输出 */
	RCC_MCU_CLKOUT_HIRC8  = 0x07,                           /*!<HIRC8时钟输出 */	
}rcc_mcuclk_out_t;
#else
typedef enum
{
	RCC_MCU_CLKOUT_NOCLK  	 = 0x00,                           /*!<无时钟输出 */
	RCC_MCU_CLKOUT_HIRC24_12 = 0x01,                           /*!<HIRC24 12MHz时钟输出 */
	RCC_MCU_CLKOUT_LIRC2  	 = 0x02,                           /*!<LIRC2时钟输出 */
	RCC_MCU_CLKOUT_HIRC24_24 = 0x03,                           /*!<HIRC24 24MHz时钟输出 */
	RCC_MCU_CLKOUT_SYSCLK 	 = 0x04,                           /*!<系统时钟输出 */
}rcc_mcuclk_out_t;

#define SYSCLK_S_HIRC24_24M     24                              /*!<系统时钟输出 HIRC24 24MHz时钟*/

#endif

/**
 * @brief  时钟输出分频选择
 */
typedef enum
{
	RCC_CLKOUT_PDIV_1   = 0x00,                             /*!<时钟输出分频为 1 */
	RCC_CLKOUT_PDIV_8   = 0x03,                             /*!<时钟输出分频为 8 */
	RCC_CLKOUT_PDIV_16  = 0x04,                             /*!<时钟输出分频为 16 */
	RCC_CLKOUT_PDIV_32  = 0x05,                             /*!<时钟输出分频为 32 */
	RCC_CLKOUT_PDIV_64  = 0x06,                             /*!<时钟输出分频为 64 */
	RCC_CLKOUT_PDIV_128 = 0x07,                             /*!<时钟输出分频为 128 */
}rcc_mcuclk_prescaler_t;

/**
 * @brief  外设复位选择
 */
typedef enum
{
#ifdef __CSA37F70__	
	RCC_PERIP_TK_RST    = 0x00,                             /*!<TK模块复位 */
#endif
	RCC_PERIP_AFE_RST   = 0x01,                             /*!<AFE模块复位 */
	RCC_PERIP_TMR1_RST  = 0x02,                             /*!<TIMER1模块复位 */
	RCC_PERIP_TMR0_RST  = 0x03,                             /*!<TIMER0模块复位 */
	RCC_PERIP_I2C_RST   = 0x04,                             /*!<I2C模块复位 */
#ifdef __CSA37F70__
	RCC_PERIP_CRC_RST   = 0x05,                             /*!<CRC模块复位 */
	RCC_PERIP_HDIV_RST  = 0x06,                             /*!<HDIV模块复位 */
#endif
	RCC_PERIP_UART_RST  = 0x07,                             /*!<UART模块复位 */
	RCC_PERIP_GPIOA_RST = 0x08,                             /*!<GPIOA模块复位 */
	RCC_PERIP_GPIOB_RST = 0x09,                             /*!<GPIOB模块复位 */
}rcc_peripheralsrst_t;

/**
 * @brief  指定查询的外设选择
 */
typedef enum
{
	RCC_FLAG_RSTS_SYS  = 0x00,                              /*!<系统复位标志 */
	RCC_FLAG_RSTS_IWDG = 0x01,                              /*!<独立看门狗复位标志 */
	RCC_FLAG_RSTS_MCU  = 0x02,                              /*!<MCU复位标志 */
	RCC_FLAG_RSTS_SRAM = 0x03,                              /*!<SRAM校验失败复位标志 */
	RCC_FLAG_RSTS_WWDG = 0x04,                              /*!<窗看门狗复位标志 */
	RCC_FLAG_RSTS_PIN  = 0x05,                              /*!<硬件复位引脚复位标志 */
 	RCC_FLAG_RSTS_POR  = 0x06,                              /*!<上电复位标志 */
}rcc_rst_status_t;

/**
 * @brief  指定查询的时钟选择
 */
typedef enum
{
	RCC_CLKS_STATE_SW_FAIL   = 0x00,                         /*!<时钟切换失败 */
	RCC_CLKS_STATE_HIRC8_STB = 0x01,                         /*!<内部8MHz高速振荡器稳定 */
	RCC_CLKS_STATE_PLL_STB   = 0x02,                         /*!<PLLCLK稳定 */
}rcc_clkstate_t;

/**
 * @brief  系统时钟源选择
 */
typedef enum
{
	RCC_SYSCLK_HIRC8   = 0x00,                              /*!<系统时钟源为8M时钟 */
	RCC_SYSCLKS_PLLCLK = 0x01,                              /*!<系统时钟源为PLL，可选24M/48M */
}rcc_sysclk_t;

/**
 * @brief  外设时钟源选择
 */
typedef enum
{
	RCC_CLKSOURCE_SYSCLK       = 0x00,                      /*!<系统时钟源 */
    RCC_CLKSOURCE_PCLK         = 0x01,                      /*!<外设时钟源 */
    RCC_CLKSOURCE_PCLK_DIV_4   = 0x02,                      /*!<外设时钟4分频 */
    RCC_CLKSOURCE_HIRC14       = 0x04,                      /*!<14M内部高速时钟 */
    RCC_CLKSOURCE_HIRC8_DIV_40 = 0x05,                      /*!<8M内部高速时钟40分频 */
    RCC_CLKSOURCE_LIRC200K     = 0x06,                      /*!<200k内部低速时钟源 */
    RCC_CLKSOURCE_HIRC8        = 0x07,                      /*!<8M内部高速时钟源 */
    RCC_CLKSOURCE_LIRC         = 0x08,                      /*!<2k低速内部时钟源 */
}rcc_clksource_t;

/**
 * @brief  外设时钟分频选择
 */
typedef enum
{
	RCC_PCLK_FREQ_HCLK        = 0x00,                       /*!<外设时钟不分频 */
	RCC_PCLK_FREQ_HCLK_DIV_2  = 0x04,                       /*!<外设时钟2分频 */
	RCC_PCLK_FREQ_HCLK_DIV_4  = 0x05,                       /*!<外设时钟4分频 */
	RCC_PCLK_FREQ_HCLK_DIV_8  = 0x06,                       /*!<外设时钟8分频 */
	RCC_PCLK_FREQ_HCLK_DIV_16 = 0x07,                       /*!<外设时钟16分频 */
}rcc_pclk_freq_t;

/**
 * @brief  HCLK时钟分频选择
 */
typedef enum
{
	RCC_HCLK_FREQ_SYSCLK         = 0x00,                    /*!<HCLK时钟不分频 */
	RCC_HCLK_FREQ_SYSCLK_DIV_2   = 0x08,                    /*!<HCLK时钟2分频 */
	RCC_HCLK_FREQ_SYSCLK_DIV_4   = 0x09,                    /*!<HCLK时钟4分频 */
	RCC_HCLK_FREQ_SYSCLK_DIV_8   = 0x0A,                    /*!<HCLK时钟8分频 */
	RCC_HCLK_FREQ_SYSCLK_DIV_16  = 0x0B,                    /*!<HCLK时钟16分频 */
	RCC_HCLK_FREQ_SYSCLK_DIV_64  = 0x0C,                    /*!<HCLK时钟64分频 */
	RCC_HCLK_FREQ_SYSCLK_DIV_128 = 0x0D,                    /*!<HCLK时钟128分频 */
	RCC_HCLK_FREQ_SYSCLK_DIV_256 = 0x0E,                    /*!<HCLK时钟256分频 */
	RCC_HCLK_FREQ_SYSCLK_DIV_512 = 0x0F,                    /*!<HCLK时钟512分频 */

}rcc_hclk_freq_t;

/**@brief	        读取系统复位状态
 *
 * @param[in]	    flag  指定要检查的标志
 * @return		    输入的标志的状态
*/
bit_status_t system_reset_status_read(rcc_rst_status_t flag);

/**@brief	        清除系统相关状态位
 *
 * @param[in]	    flag  指定要清除的标志
 * @return		    无
*/
void system_reset_status_clear(rcc_rst_status_t flag);

/**@brief	        芯片软复位设置
 *
 * @param[in]	    flag  指定芯片复位的模式
 * @return		    无
*/
void chip_soft_reset_enable(rcc_chiprst_t flag);

/**@brief	        芯片外设复位控制
 *
 * @param[in]	    flag  指定要复位的外设模块
 * @param[in]	    state  使能/禁止选择
 * @return		    无
*/
void chip_peripherals_reset_config(rcc_peripheralsrst_t flag,enable_state_t state);

#ifdef __CSA37F70__
/**@brief	        Flash读速度控制
 *
 * @param[in]	    flag  读速度选择
 * @return		    无
*/
void flash_read_speed_set(rcc_flashread_t flag);
#endif

/**@brief	        选择微控制器时钟输出及分频
 *
 * @param[in]	    clk_value  指定要输出的时钟源
 * @param[in]	    prescaler  分频系数
 * @return		    无
*/
void rcc_mcu_clk_config(rcc_mcuclk_out_t clk_value, rcc_mcuclk_prescaler_t prescaler);

/**@brief	        内部14M RC使能或禁止
 *
 * @param[in]	    state  使能/禁止选择
 * @return		    无
*/
void rcc_hirc14_enable_set(enable_state_t state);

/**@brief	        AHB外设时钟开关
 *
 * @param[in]	    RCC_AHBPeriph  选择的外设模块
 * @param[in]	    state  使能/禁止选择
 * @return		    无
*/
void rcc_ahb_periph_clock_config(uint32_t RCC_AHBPeriph,enable_state_t state);

/**@brief	        APB外设时钟开关
 *
 * @param[in]	    RCC_APBPeriph  选择的外设模块
 * @param[in]	    state  使能/禁止选择
 * @return		    无
*/
void rcc_apb_periph_clock_config(uint32_t RCC_APBPeriph,enable_state_t state);

#ifdef __CSA37F70__
/**@brief	        获取相关时钟状态
 *
 * @param[in]	    flag  选择的时钟类型
 * @return		    指定时钟的状态 1: 稳定或成功   0: 不稳定或者失败
*/
uint8_t rcc_clk_status_get(rcc_clkstate_t flag);

/**@brief	        系统时钟选择
 *
 * @param[in]	    flag  选择的系统时钟源
 * @return		    无
*/
void rcc_sysclk_config(rcc_sysclk_t flag);

/**@brief	        串口时钟源选择
 *
 * @param[in]	    flag  串口时钟源选择
 * @return		    无
*/
void rcc_uart_clksource_config(rcc_clksource_t flag);

/**@brief	        ADC时钟源选择
 *
 * @param[in]	    flag  ADC时钟源选择
 * @return		    无
*/
void rcc_adc_clksource_config(rcc_clksource_t flag);

/**@brief	        TK时钟源选择
 *
 * @param[in]	    flag  TK时钟源选择
 * @return		    无
*/
void rcc_tk_clksource_config(rcc_clksource_t flag);
#endif

/**@brief	        TIMER1时钟源选择
 *
 * @param[in]	    flag  TIMER1时钟源选择
 * @return		    无
*/
void rcc_timer1_clksource_config(rcc_clksource_t flag);

/**@brief	        PCLK时钟分频设置
 *
 * @param[in]	    rcc_pclkfreq  PCLK选择的分频系数
 * @return		    无
*/
void rcc_pclk_config(rcc_pclk_freq_t rcc_pclkfreq);

/**@brief	        HCLK时钟分频设置
 *
 * @param[in]	    rcc_hclkfreq  HCLK选择的分频系数
 * @return		    无
*/
void rcc_hclk_config(rcc_hclk_freq_t rcc_hclkfreq);

#ifdef __CSA37F70__
/**@brief	        PLL输出时钟选择
 *
 * @param[in]	    flag  PLL输出时钟选择
 * @return		    无
*/
void rcc_pll_clk_set(rcc_pllclk_t flag);

/**@brief	        PLL使能
 *
 * @return		    无
*/
void rcc_pll_enable(void);

/**@brief	        禁止PLL
 *
 * @return		    无
*/
void rcc_pll_disable(void);

/**@brief	        TK 200k时钟使能
 *
 * @return		    无
*/
void rcc_tk_200k_osi_enable(void);

/**@brief	        禁止TK 200k时钟
 *
 * @return		    无
*/
void rcc_tk_200k_osi_disable(void);

/**@brief	       TK 锁定中断使能
 *
 * @return		    无
*/
void rcc_pll_lock_interrupt_enable(void);

/**@brief	        禁止TK 锁定中断
 *
 * @return		    无
*/
void rcc_pll_lock_interrupt_disable(void);

/**@brief	        TK 解锁中断使能
 *
 * @return		    无
*/
void rcc_pll_unlock_interrupt_enable(void);

/**@brief	        禁止TK 解锁中断
 *
 * @return		    无
*/
void rcc_pll_unlock_interrupt_disable(void);

/**@brief	        获取系统时钟
 *
 * @return		    系统时钟数：8/24/48
*/
uint8_t rcc_sysclk_get(void);
#endif

/*@}*/ /* end of group RCC */

#ifdef __cplusplus
}
#endif

#endif  //__CSA37F7X_RCC_H__


/*** (C) COPYRIGHT 2020 Chipsea Technologies (Shenzhen) Corp. ***/
